package org.example.demo3.common.utils;


import cn.hutool.json.JSONUtil;
//import jakarta.websocket.*;
//import jakarta.websocket.server.PathParam;
//import jakarta.websocket.server.ServerEndpoint;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.example.demo3.pojo.entity.SocketMsg;
import org.springframework.boot.autoconfigure.web.reactive.WebFluxProperties;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;


@Slf4j
@Component
@ServerEndpoint("/test/websocket/{userName}/{roomId}")
public class WebSocketUtil {

    private String userName;
    private Session session;
    private String roomId;

    /**
     * 固定前缀
     */
    private static final String USER_NAME_PREFIX = "user_name_";   //sessionMap里面加这个，groupSessionMap不加

    /**
     * 存放Session集合，方便推送消息 （jakarta.websocket）
     */
    private static ConcurrentHashMap<String, Session> sessionMap = new ConcurrentHashMap<>();

    /**
     * 存放房间用户集合，方便推送消息 （jakarta.websocket）
     */
    private static HashMap<String, List<String>> groupSessionMap = new HashMap<>();

    /**
     * 群聊：向指定房间ID推送消息
     */
    public synchronized static void groupMessage(SocketMsg socketMsg) {
        // 存储房间号和用户信息
        String roomId = socketMsg.getRoomId();
        // 判断是否有这个房间
        List<String> strings = groupSessionMap.get(roomId); //返回这个房间的用户名列表

        // 发送给接收者
        if (roomId != null) {
            // 发送给接收者
            System.out.println(socketMsg.getSendOutUser() + " 向房间 【 " + roomId + " 】 发送了一条消息：" + socketMsg.getMsg());
            System.out.println("onmessage show:"+groupSessionMap);
            // 此时要判断房间有哪些人，把这些消息定向发给处于此房间的用户
            List<String> roomUser = groupSessionMap.get(roomId);
            for (String userName : roomUser) {
                if(userName.equals(socketMsg.getSendOutUser())){
                    continue;
                }

                userName=USER_NAME_PREFIX+userName;
                // 接收消息的用户
                log.info("i check out...................................");
                Session receiveUser = sessionMap.get(userName);
                 synchronized(receiveUser){
                        receiveUser.getAsyncRemote().sendText(socketMsg.getSendOutUser()+","+socketMsg.getMsg());
                 }

            }
        } else {
            // 发送消息的用户
            Session sendOutUser = sessionMap.get(USER_NAME_PREFIX + socketMsg.getSendOutUser());
            // 将系统提示推送给发送者
            sendOutUser.getAsyncRemote().sendText("系统消息：对方不在线或者您输入的用户名不对");
        }
    }

    /**
     * 全局消息：公开聊天记录
     *
     * @param message 发送的消息
     */
    public synchronized static void publicMessage(String message, String roomId ,String username) throws IOException {

        List<String> list=groupSessionMap.get(roomId);
        for (String str : list) {

            String name=USER_NAME_PREFIX+str;
            Session session=sessionMap.get(name);

            Session session1=sessionMap.get(USER_NAME_PREFIX+username);
            if (session1 != null && session1.isOpen()){
                session1.getBasicRemote().sendText("列表:"+str);
            }

            if(username.equals(str)){
                continue;
            }
            if (session != null && session.isOpen()){
                session.getBasicRemote().sendText(message);
            }

            log.info("message publicSend......");
            System.out.println("公共频道接收了一条消息"+message);
        }

    }

    /**
     * 监听：连接成功
     *
     * @param session
     * @param userName 连接的用户名
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userName") String userName,@PathParam("roomId") String roomId) throws IOException {  //username通过路径参数发过来,roomId同理
        this.userName = userName;
        this.session = session;
        this.roomId=roomId;
        log.info("connection success.....");
        String name = USER_NAME_PREFIX + userName;   //加前缀为user_name_
        if (!sessionMap.containsKey(name)) {    //判断sessionMap里面有没有这个人的对象，没有就加入
            sessionMap.put(name, session);
            // 在线数加1
        }

        List<String> strings = groupSessionMap.get(roomId); //返回这个房间的用户名列表

        if(strings == null){
            List<String> users=new ArrayList<>();
            users.add(this.userName);
            groupSessionMap.put(roomId, users);

        }else if(!strings.contains(this.userName)){
            strings.add(this.userName);
        }
        System.out.println("onopen show :"+groupSessionMap);

            String tips ="用户" + " '"+userName+"' "+"加入了房间！";
            System.out.println(tips);

            publicMessage(tips,this.roomId,this.userName);

    }

    /**
     * 监听: 连接关闭
     */
    @OnClose
    public void onClose() {
        String tips = userName + " 退出聊天室。当前聊天室人数为" + sessionMap.size();
        System.out.println(tips);
        String name = USER_NAME_PREFIX + this.userName;

        sessionMap.remove(name);
        groupSessionMap.get(roomId).remove(userName);

        List<String> list=groupSessionMap.get(roomId); //群发消息xxx退出了房间
         for (String str : list) {

            String name1=USER_NAME_PREFIX+str;
            Session session=sessionMap.get(name1);
            if(str.equals(userName)){
                continue;
            }
            session.getAsyncRemote().sendText("退出:"+userName);
            log.info("message outRoomSend......"+userName);
        }



    }

    /**
     * 监听：收到客户端发送的消息
     *
     * @param message 发送的信息（json格式，里面是 SocketMsg 的信息）
     */
    @OnMessage
    public void onMessage(String message) throws IOException {  //只需要传输message，因为session和name已经赋值给这个对象本身了，在open的时候
        if (JSONUtil.isTypeJSONObject(message)) {
            SocketMsg socketMsg = JSONUtil.toBean(message, SocketMsg.class);   //把传过来的message转变呈socketMsg对象
            if (socketMsg.getType() == 2) {
                // 群聊，需要找到发送者和房间ID
                groupMessage(socketMsg);
//            } else if (socketMsg.getType() == 1) {
//                // 单聊，需要找到发送者和接受者
//                privateMessage(socketMsg);
            } else {
                // 全局广播群发消息
                publicMessage(socketMsg.getMsg(),roomId,userName);
            }
        }
    }

    /**
     * 监听：发生异常
     *
     * @param error
     */
    @OnError
    public void onError(Throwable error) {
        System.out.println("userName：" + userName + "hava wrong:" + error.getMessage());
        error.printStackTrace();
    }

}



